﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DDD.Core;
using FloatComparer = DDDTest.Helper.FloatComparer;

namespace DDDTest.Core {
    [TestClass]
    public class TestShaderProgram {
        string vert = @"#version 400
                         in  vec3 v_Position;
                               
                         void main () {
                             gl_Position = vec4(v_Position, 1);
                         }
                        ";
        string frag = @"#version 400
                         out vec4 frag_Color;
                               
                         void main () {
                             frag_Color = vec4(0,0,1,1);
                         }
                        ";

        /// <summary>
        /// コンストラクターのテスト
        /// </summary>
        /// <remarks>
        /// (*1) この時点ではまだコンパイル＆リンクされていないのでUniform変数とAttribute変数の数は0.
        /// </remarks>
        [TestMethod]
        public void Test_New1 () {
            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);

            Assert.AreEqual ("", sp.LinkLog);
            Assert.AreEqual (0, sp.AttributeCount);       // (*1)
            Assert.AreEqual (0, sp.UniformCount);         // (*1)
            Assert.AreEqual (0, sp.FeedbackVaryingCount);
        }

        [TestMethod]
        public void Test_AddFeedbackVarying () {
            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);

            sp.SetTransformFeedbackEnable (true, 2);
            sp.SetFeedbackVarying (0, "Hello");
            sp.SetFeedbackVarying (1, "World");

            Assert.AreEqual (2, sp.FeedbackVaryingCount);
            Assert.AreEqual (2, sp.FeedbackVaryings.Count ());
        }

        [TestMethod]
        public void Test_RemoveFeedbackVarying () {
            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);

            sp.SetTransformFeedbackEnable (true, 2);
            sp.SetFeedbackVarying (0, "Hello");
            sp.SetFeedbackVarying (1, "World");
            sp.RemoveFeedbackVarying ("Hello");
            sp.RemoveFeedbackVarying ("World");

            Assert.AreEqual (2, sp.FeedbackVaryingCount);
            Assert.AreEqual (0, sp.FeedbackVaryings.Count ());
        }

        [TestMethod]
        public void Test_References () {
            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);

            var objs = sp.References;

            Assert.AreEqual (2, objs.Count ());
            Assert.AreEqual (true, objs.All (x => x != null));
        }

        [TestMethod]
        public void Test_Find () {
            var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var sp = new ShaderProgram (vs, fs);
            vs.UserID = 101;
            fs.UserID = 102;
            sp.UserID = 103;

            Assert.AreEqual (vs, sp.Find (101));
            Assert.AreEqual (fs, sp.Find (102));
            Assert.AreEqual (sp, sp.Find (103));
        }
    }
}
